#!/usr/bin/env python

#    Copyright 2011,2012 Erik Persson
#
#    This file is part of the cell-sync-usrp project.
#
#    cell-sync-usrp is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    cell-sync-usrp is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with cell-sync-usrp.  If not, see <http://www.gnu.org/licenses/>.


##################################################
# Gnuradio Python Flow Graph
# Title: Top Block
# Generated: Tue Oct 25 19:56:16 2011
##################################################

# decoding stuff
import sys
sys.path.append( "../convolution" )
import convolution
import CRC
import RSSIScan
import argparse


# gnu radio stuff
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import uhd
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from grc_gnuradio import wxgui as grc_wxgui
from optparse import OptionParser
import wcdma
import wx

class top_block(grc_wxgui.top_block_gui):

	def __init__(self):
		grc_wxgui.top_block_gui.__init__(self, title="Top Block")

		##################################################
		# Variables
		##################################################
		self.samp_rate = samp_rate = 3.84e6*2
		self.frequency = frequency = 2.14e9

		##################################################
		# Blocks
		##################################################
		self.wcdma_slot_sync_cvc_0 = wcdma.slot_sync_cvc()
		self.wcdma_slot_sync_cvc_0.isDone()
		self.wcdma_resampler_cc_0 = wcdma.resampler_cc(7.692308/7.680000)
		self.uhd_usrp_source_0 = uhd.usrp_source(
			device_addr="",
			io_type=uhd.io_type.COMPLEX_FLOAT32,
			num_channels=1,
		)
		self.uhd_usrp_source_0.set_samp_rate(samp_rate)
		self.uhd_usrp_source_0.set_center_freq(frequency, 0)
		self.uhd_usrp_source_0.set_gain(1000, 0)
		self.root_raised_cosine_filter_1 = gr.fir_filter_ccf(1, firdes.root_raised_cosine(
			1, samp_rate, samp_rate/2, 0.22, 30))
		self.gr_null_sink_0 = gr.null_sink(gr.sizeof_gr_complex*1)
		#self.gr_agc_xx_0 = gr.agc_cc(1e-4, 1.0, 1.0, 5.0)

		##################################################
		# Connections
		##################################################
		self.connect((self.wcdma_slot_sync_cvc_0, 0), (self.gr_null_sink_0, 0))
		self.connect((self.root_raised_cosine_filter_1, 0), (self.wcdma_slot_sync_cvc_0, 0))
		self.connect((self.uhd_usrp_source_0, 0), (self.wcdma_resampler_cc_0, 0))
		#self.connect((self.uhd_usrp_source_0, 0), (self.gr_agc_xx_0, 0))
		#self.connect((self.gr_agc_xx_0, 0), (self.wcdma_resampler_cc_0, 0))
		self.connect((self.wcdma_resampler_cc_0, 0), (self.root_raised_cosine_filter_1, 0))

	def get_samp_rate(self):
		return self.samp_rate

	def set_samp_rate(self, samp_rate):
		self.samp_rate = samp_rate
		self.root_raised_cosine_filter_1.set_taps(firdes.root_raised_cosine(1, self.samp_rate, 1.0, 0.22, 3))
		self.uhd_usrp_source_0.set_samp_rate(self.samp_rate)

	def get_frequency(self):
		return self.frequency

	def set_frequency(self, frequency):
		self.frequency = frequency
		self.uhd_usrp_source_0.set_center_freq(self.frequency, 0)

# takes a list and groups the elements in pairs of two and returns the new list
def pair(seq):
    ret = []
    d = []
    for a in seq:
        d.append(a)
        if (len(d) == 2):
            ret.append(d)
            d = []
    if (len(d) != 0):
        ret.append(d)
    
    return ret

def decode(PCCPCH,tries):
	#global CRCCalc
	#global conv
	
	nofTries = 0 # number of CRC errors before giving up
	
	# decode PCCPCH data turning it into BCH data
	
	# first de-interleaving mapping
	mapping = [0, 30, 60, 90, 120, 150, 180, 210, 240, 20, 50, 80, 110, 140, 170, 200, 230, 260, 10, 40, 70, 100, 130, 160, 190, 220, 250, 5, 35, 65, 95, 125, 155, 185, 215, 245, 15, 45, 75, 105, 135, 165, 195, 225, 255, 25, 55, 85, 115, 145, 175, 205, 235, 265, 3, 33, 63, 93, 123, 153, 183, 213, 243, 13, 43, 73, 103, 133, 163, 193, 223, 253, 23, 53, 83, 113, 143, 173, 203, 233, 263, 8, 38, 68, 98, 128, 158, 188, 218, 248, 18, 48, 78, 108, 138, 168, 198, 228, 258, 28, 58, 88, 118, 148, 178, 208, 238, 268, 1, 31, 61, 91, 121, 151, 181, 211, 241, 11, 41, 71, 101, 131, 161, 191, 221, 251, 21, 51, 81, 111, 141, 171, 201, 231, 261, 6, 36, 66, 96, 126, 156, 186, 216, 246, 16, 46, 76, 106, 136, 166, 196, 226, 256, 26, 56, 86, 116, 146, 176, 206, 236, 266, 4, 34, 64, 94, 124, 154, 184, 214, 244, 14, 44, 74, 104, 134, 164, 194, 224, 254, 24, 54, 84, 114, 144, 174, 204, 234, 264, 19, 49, 79, 109, 139, 169, 199, 229, 259, 9, 39, 69, 99, 129, 159, 189, 219, 249, 29, 59, 89, 119, 149, 179, 209, 239, 269, 12, 42, 72, 102, 132, 162, 192, 222, 252, 2, 32, 62, 92, 122, 152, 182, 212, 242, 7, 37, 67, 97, 127, 157, 187, 217, 247, 22, 52, 82, 112, 142, 172, 202, 232, 262, 27, 57, 87, 117, 147, 177, 207, 237, 267, 17, 47, 77, 107, 137, 167, 197, 227, 257]
	# second de-interleaving mapping
	mapping2 = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459, 461, 463, 465, 467, 469, 471, 473, 475, 477, 479, 481, 483, 485, 487, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539]
   	
	conv = convolution.Convolution(9,2,[[0,2,3,4,8],[0,1,2,3,5,7,8]])
	CRCCalc = CRC.CRC16()
	
   	nofFrames = len(PCCPCH)
   	nofBCHTTIs = nofFrames / 2

   	BCHReturn = []
   	BCHFrameNr = 0
   	print "NofBCHFrames: " + str(nofBCHTTIs)
   	while (BCHFrameNr < nofBCHTTIs):
   		# first deinterleaving
   		tmp1 = [0] * 270
   		tmp2 = [0] * 270   
   		j = 0
   		while (j<270):
   			tmp1[mapping[j]] = PCCPCH[BCHFrameNr*2][j]
   			tmp2[mapping[j]] = PCCPCH[BCHFrameNr*2+1][j]
   			j+=1
   		frame = tmp1+tmp2

   		#second deinterleaving
   		tmp3 = [0] * 270*2
   		j = 0
   		while (j<270*2):
   			mapp = mapping2[j]
   			data = frame[j]
   			tmp3[mapp] = data
   			j+=1
   			
   		tmp3 = pair(tmp3);
   		decoded = conv.decodeSeq(tmp3,270-8)
   		print "decodedSeq.append(" + str(decoded) + ")"

   		# remove 8 last zero bits
   		i = 0
   		while i<8:
   			decoded.pop()
   			i+=1
   			
   		# remove and store CRC bits in reversed order
   		check = [0] * 16
   		i = 0
   		while (i<16):
   			check[i] = decoded.pop()
   			i+=1
   			
   		CRCCalc.clear()
   			
   		CRCCalc.insertSeq(decoded)
   		crc = CRCCalc.readCRC()
   			
   		i = 0
   		match = 0
   		while (i<16):
   			if (crc[i] == check[i]):#crcOk[i]):
   				match+=1
   			i += 1
   		
   		if (match < 16):
   			nofTries+=1	# number of fails
   			# copy decoded data
   		else:
   			nofTries = 0 # reset
   			BCHReturn.append(decoded)
   		if (nofTries >= tries):
   			return	BCHReturn  # if number of fails > tries then return
   		
   		print "CRC match: " + str(match) + " CRC" + str(crc)
        
   		print "crc: " +str(crc)
		print "BCHFrameNr: " + str(BCHFrameNr)
		BCHFrameNr += 1
	print "BCHReturn: " + str(BCHReturn)
	return BCHReturn

if __name__ == '__main__':
	#parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
	#(options, args) = parser.parse_args()
	
	parser = argparse.ArgumentParser(description='WCDMA cell sync SDR application')
	parser.add_argument('UARFCN', nargs='+', type=int, default='10638',
                    help='UARFCN (Freq = UARFCN*200000')
	args = parser.parse_args()

	tb = top_block()
	#tb.Run(True)
	print args.UARFCN
	tb.set_frequency(args.UARFCN[0]*200000)#2.1574e9)#2.1276e9)
	tb.start();
	a = 0
	while (tb.wcdma_slot_sync_cvc_0.isDone() == 0 and tb.wcdma_slot_sync_cvc_0.getNumberOfRetries() < 3):
		a+=1
	tb.stop()
	
	if (tb.wcdma_slot_sync_cvc_0.isDone() > 0):
		print "Success!!!"
		print "BCH data :" 
		print "Frame1:",
		
		PCCPCH = []
		i = 0
		NUMBER_OF_CAPTURED_PCCPCH_FRAMES = 32
		NUMBER_OF_BITS_ON_PCCPCH = 270
		while (i<NUMBER_OF_CAPTURED_PCCPCH_FRAMES):
			onePCCPCH = []
			j = 0
			while (j<NUMBER_OF_BITS_ON_PCCPCH):
				onePCCPCH.append(tb.wcdma_slot_sync_cvc_0.getPCCPCHData(i,j))
				j+=1
			PCCPCH.append(onePCCPCH)
			i+=1
				
		print PCCPCH		
		
		
		a = decode(PCCPCH,3)
		del PCCPCH[0]
		print "--------------------------"
		b = []
		if (len(a) != 16):
			b = decode(PCCPCH,3)
		c = None
		if (len(a) > len(b)):
			c = a
		else:
			c = b
			
		if (len(c)==0):
			print "Unable to read BCH"
			exit()
			
		print "Successfully read BCH!!!"
		# print SFN and BCH data
		for a in c:
			# get SFN
			SFN = 0
			i = 0
			while i<12:
				SFN += a[i]*2**(11-i)
				i+=1
			print "SFN: " + str(SFN)
			print "BCH: " + str(a)
		
		exit()
	
		# decode PCCPCH data turning it into BCH data
		
		# first de-interleaving mapping
		mapping = [0, 30, 60, 90, 120, 150, 180, 210, 240, 20, 50, 80, 110, 140, 170, 200, 230, 260, 10, 40, 70, 100, 130, 160, 190, 220, 250, 5, 35, 65, 95, 125, 155, 185, 215, 245, 15, 45, 75, 105, 135, 165, 195, 225, 255, 25, 55, 85, 115, 145, 175, 205, 235, 265, 3, 33, 63, 93, 123, 153, 183, 213, 243, 13, 43, 73, 103, 133, 163, 193, 223, 253, 23, 53, 83, 113, 143, 173, 203, 233, 263, 8, 38, 68, 98, 128, 158, 188, 218, 248, 18, 48, 78, 108, 138, 168, 198, 228, 258, 28, 58, 88, 118, 148, 178, 208, 238, 268, 1, 31, 61, 91, 121, 151, 181, 211, 241, 11, 41, 71, 101, 131, 161, 191, 221, 251, 21, 51, 81, 111, 141, 171, 201, 231, 261, 6, 36, 66, 96, 126, 156, 186, 216, 246, 16, 46, 76, 106, 136, 166, 196, 226, 256, 26, 56, 86, 116, 146, 176, 206, 236, 266, 4, 34, 64, 94, 124, 154, 184, 214, 244, 14, 44, 74, 104, 134, 164, 194, 224, 254, 24, 54, 84, 114, 144, 174, 204, 234, 264, 19, 49, 79, 109, 139, 169, 199, 229, 259, 9, 39, 69, 99, 129, 159, 189, 219, 249, 29, 59, 89, 119, 149, 179, 209, 239, 269, 12, 42, 72, 102, 132, 162, 192, 222, 252, 2, 32, 62, 92, 122, 152, 182, 212, 242, 7, 37, 67, 97, 127, 157, 187, 217, 247, 22, 52, 82, 112, 142, 172, 202, 232, 262, 27, 57, 87, 117, 147, 177, 207, 237, 267, 17, 47, 77, 107, 137, 167, 197, 227, 257]
		# second de-interleaving mapping
		mapping2 = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459, 461, 463, 465, 467, 469, 471, 473, 475, 477, 479, 481, 483, 485, 487, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539]
   		
		conv = convolution.Convolution(9,2,[[0,2,3,4,8],[0,1,2,3,5,7,8]])
		CRCCalc = CRC.CRC16()
		
   		nofFrames = len(PCCPCH)
   		nofBCHTTIs = nofFrames / 2

   		BCHFrameNr = 0
   		print "NofBCHFrames: " + str(nofBCHTTIs)
   		while (BCHFrameNr < nofBCHTTIs):
   			# first deinterleaving
   			tmp1 = [0] * 270
   			tmp2 = [0] * 270   
   			j = 0
   			while (j<270):
   				tmp1[mapping[j]] = PCCPCH[BCHFrameNr*2][j]
   				tmp2[mapping[j]] = PCCPCH[BCHFrameNr*2+1][j]
   				j+=1
   			frame = tmp1+tmp2

   			#second deinterleaving
   			tmp3 = [0] * 270*2
   			j = 0
   			while (j<270*2):
   				mapp = mapping2[j]
   				data = frame[j]
   				tmp3[mapp] = data
   				j+=1
   			
   			tmp3 = pair(tmp3);
   			decoded = conv.decodeSeq(tmp3,270-8)
   			print "decodedSeq.append(" + str(decoded) + ")"

   			# remove 8 last zero bits
   			i = 0
   			while i<8:
   				decoded.pop()
   				i+=1
   			
   			# remove and store CRC bits in reversed order
   			check = [0] * 16
   			i = 0
   			while (i<16):
   				check[i] = decoded.pop()
   				i+=1
   			
   			CRCCalc.clear()
   			
   			CRCCalc.insertSeq(decoded)
   			crc = CRCCalc.readCRC()
   			
   			i = 0
   			match = 0
   			while (i<16):
   				if (crc[i] == check[i]):#crcOk[i]):
   					match+=1
   				i += 1
                
   			print "CRC match: " + str(match) + " CRC" + str(crc)
        
   			print "crc: " +str(crc)
			print "BCHFrameNr: " + str(BCHFrameNr)
			BCHFrameNr += 1

		
